#include "hailstone.hh"
#include <regex>
#include <iostream>
#include <string>
#include <vector>
#include <cstring>
#include <cassert>
#include <sstream>

auto split(const std::string& origin, const char* token) -> std::vector<std::string>
{
    std::vector<std::string> result {};

    std::size_t begin {0};
    std::size_t end {0};
    while ((end = origin.find(token, begin)) != std::string::npos)
    {
        result.emplace_back(origin.substr(begin, end - begin));
        begin = end + std::strlen(token);
    }
    result.emplace_back(origin.substr(begin, origin.size() - begin));

    return result;
}

Hailstone::Hailstone(const std::string& s)
{
    // 233210433951170, 272655040388795, 179982504986147 @ 39, -98, 166
    std::vector<std::string> positionsAndSpeeds {split(s, " @ ")};
    assert(positionsAndSpeeds.size() == 2);

    std::vector<std::string> positions {split(positionsAndSpeeds[0], ", ")};
    assert(positions.size() == 3);
    this->positionX = std::stod(positions[0]);
    this->positionY = std::stod(positions[1]);
    this->positionZ = std::stod(positions[2]);

    std::vector<std::string> speeds {split(positionsAndSpeeds[1], ", ")};
    assert(speeds.size() == 3);
    this->speedX = std::stod(speeds[0]);
    this->speedY = std::stod(speeds[1]);
    this->speedZ = std::stod(speeds[2]);
}

std::string Hailstone::toString() const
{
    std::stringstream ss {};
    ss << this->positionX << ", " << this->positionY << ", " << this->positionZ << " @ "
       << this->speedX << ", " << this->speedY << ", " << this->speedZ;
    return ss.str();
}

bool Hailstone::isInLine(double x, double y) const
{
    if (x == this->positionX && y == this->positionY)
        return true;
    return (this->speedX * (x - this->positionX) > 0) && (this->speedY * (y - this->positionY) > 0);
}